﻿using System;
using System.IO;
using System.Linq;
using NUnit.Framework;
using SharpSvn;
using SvnFlow;
using System.Collections.Generic;

namespace SvnFlowTests
{
    [TestFixture]
    public class BranchesFileTests
    {
        [Test]
        public void CreateEmptyTest()
        {
            var fileName = Path.GetFullPath("empty.xml");
            BranchesFile.CreateEmpty(fileName, DateTime.Parse("2010-11-09T22:00:00.000"), null);
            TestHelper.AssertXmlFileEquals(TestHelper.EmptyBranchesXml, fileName);
            File.Delete(fileName);
        }

        [Test]
        public void GenerateTest()
        {
            var helper = new TestHelper();
            var flowClient = new FlowSvnClient(new SvnClient());
            var file = Path.GetFullPath("generated.xml");
            var client = new SvnClient();
            SvnInfoEventArgs info;

            TestHelper.ReCreateRepositoryFromDump(TestHelper.m_repo1Path, TestHelper.Rep1DumpName);
            SvnHelper.DeleteRecursiveFolder(TestHelper.m_work1Path);
            TestHelper.ReCreateRepositoryFromDump(TestHelper.m_repo2Path, TestHelper.Rep2DumpName);
            SvnHelper.DeleteRecursiveFolder(TestHelper.m_work2Path);

            flowClient.PrepareWorkingCopy(helper.branchFrom);
            flowClient.PrepareWorkingCopy(helper.branchTo);

            BranchesFile.CreateEmpty(file, DateTime.Parse("2010-11-09T22:00:00.000"), 
                new CmdOptions { GeneratePath = new []{ TestHelper.m_work1Path, TestHelper.m_work2Path } });
            var branches = new BranchesFile(file);

            client.GetInfo(new SvnPathTarget(TestHelper.m_work1Path), out info);
            var historyItem = branches.m_branches.History.Where(x => x.FromBranch == "left").FirstOrDefault();
            Assert.That(historyItem,Is.Not.Null);
            Assert.That(historyItem.LastMergedRevision,Is.EqualTo(info.LastChangeRevision));

            client.GetInfo(new SvnPathTarget(TestHelper.m_work2Path), out info);
            historyItem = branches.m_branches.History.Where(x => x.FromBranch == "right").FirstOrDefault();
            Assert.That(historyItem, Is.Not.Null);
            Assert.That(historyItem.LastMergedRevision, Is.EqualTo(info.LastChangeRevision));

            SvnHelper.DeleteRecursiveFolder(TestHelper.m_work1Path);
            SvnHelper.DeleteRecursiveFolder(TestHelper.m_work2Path);
            TestHelper.DeleteRepository(TestHelper.m_repo1Path);
            TestHelper.DeleteRepository(TestHelper.m_repo2Path);
            File.Delete(file);
        }

        [Test]
        public void LoadBranchesFileTest()
        {
            var testFileName = Path.GetFullPath("test.xml");
            if (File.Exists(testFileName)) File.Delete(testFileName);

            // file doesn't exist
            Assert.Throws<ArgumentException>(()=> new BranchesFile(testFileName));

            // error: Uri in left branch is missing or empty
            File.WriteAllText(testFileName, TestHelper.Error1BranchesXml);
            Assert.That(() => new BranchesFile(testFileName),
                Throws.TypeOf<ArgumentNullException>().With.Message.EqualTo(TestHelper.Error1BranchesXmlMessage));

            // error: Branch left is missing
            File.WriteAllText(testFileName, TestHelper.Error2BranchesXml);
            Assert.That(() => new BranchesFile(testFileName),
                Throws.TypeOf<ArgumentNullException>().With.Message.EqualTo(TestHelper.Error2BranchesXmlMessage));

            // valid config file with empty history
            File.WriteAllText(testFileName, TestHelper.Error3BranchesXml);
            var branchesFile = new BranchesFile(testFileName);
            Assert.That(branchesFile.m_branches.History, Is.Empty);

            // valid config file with non-empty history
            File.WriteAllText(testFileName, TestHelper.Error4BranchesXml);
            branchesFile = new BranchesFile(testFileName);
            var expectedHistory = new List<HistoryItem>
			                  	{
			                  		new HistoryItem
			                  			{
			                  				Time = "2010-10-09T11:00:00.000",
			                  				FromBranch = "left",
			                  				LastMergedRevision = 1
			                  			}
			                  	};
            Assert.That(branchesFile.m_branches.History.Count, Is.EqualTo(1));
            Assert.That(branchesFile.m_branches.History, Is.EquivalentTo(expectedHistory));
            Assert.That(branchesFile.m_branches.MappedFolders, Is.Empty);
        }

        [Test]
        public void SaveTest()
        {
            var sampleFileName = Path.GetFullPath("Branches.xml");
            var saveFileName = Path.GetFullPath("save.xml");
            
            var branchesFile = new BranchesFile(sampleFileName);
            branchesFile.Save(saveFileName);

            TestHelper.AssertXmlFileEquals(File.ReadAllText(sampleFileName), saveFileName);
            
            File.Delete(saveFileName);
        }

        [Test]
        public void CreateBranchInfoTest()
        {
            var fileName = Path.GetFullPath("Branches.xml");
            var branchesFile = new BranchesFile(fileName);
            var branchLeft = branchesFile.CreateBranchInfo("left");
            Assert.That(branchLeft, Is.EqualTo(
                new BranchInfo(
                    new Uri("file:///D:/TEST.rep.1/"),
                    "left",
                    Path.Combine(Path.GetDirectoryName(fileName), "left"),
                    new SvnRevisionRange(0,1))
                )
            );
            var branchRight = branchesFile.CreateBranchInfo("right");
            Assert.That(branchRight, Is.EqualTo(
                new BranchInfo(
                    new Uri("file:///D:/TEST.rep.2/"),
                    "right",
                    Path.Combine(Path.GetDirectoryName(fileName), "right"),
                    new SvnRevisionRange(0,0))
                )
            );

            var branchAny = branchesFile.CreateBranchInfo("any");
            Assert.That(branchAny, Is.Null);
        }

        [Test]
        public void AddHistoryItemTest()
        {
            var testFileName = Path.GetFullPath("test.xml");
            if (File.Exists(testFileName)) File.Delete(testFileName);

            File.WriteAllText(testFileName, TestHelper.HistoryBranchesXml);
            BranchesFile branchesFile = null;
            Assert.DoesNotThrow(delegate { branchesFile = new BranchesFile(testFileName); });
            Assert.That(branchesFile.m_branches.History, Is.TypeOf<List<HistoryItem>>());
            var testHistory = new List<HistoryItem>
			                  	{
			                  		new HistoryItem
			                  			{
			                  				Time = "2010-10-09T11:00:00.000",
			                  				FromBranch = "left",
			                  				LastMergedRevision = 1
			                  			}
			                  	};
            Assert.That(branchesFile.m_branches.History.Count, Is.EqualTo(1));
            Assert.That(branchesFile.m_branches.History, Is.EquivalentTo(testHistory));

            branchesFile.AddHistoryItem(
                DateTime.Parse("2010-10-09T12:00:00.000"),
                "left",
                "right",
                new SvnRevisionRange(1, 2)
            );

            testHistory.Add(
                            new HistoryItem
                                        {
                                            Time = "2010-10-09T12:00:00.000",
                                            FromBranch = "left",
                                            LastMergedRevision = 2
                                        }
                             );
            Assert.That(branchesFile.m_branches.History.Count, Is.EqualTo(2));
            Assert.That(branchesFile.m_branches.History, Is.EquivalentTo(testHistory));
        }

        [Test]
        public void FolderMapTest()
        {
            var testFileName = Path.GetFullPath("test.xml");
            if (File.Exists(testFileName)) File.Delete(testFileName);

            File.WriteAllText(testFileName, TestHelper.FolderMapBranchesXml);
            BranchesFile branchesFile = null;
            Assert.DoesNotThrow(delegate { branchesFile = new BranchesFile(testFileName); });
            Assert.That(branchesFile.m_branches.MappedFolders, Is.TypeOf<List<FolderMap>>());
            Assert.That(branchesFile.m_branches.MappedFolders, Is.EquivalentTo(
                    new List<FolderMap>
                        {
                            new FolderMap { Left = "1", Right = "2" },
                            new FolderMap { Left = "3", Right = "4" }
                        }
                ));
        }
    }
}
